# -*- coding: utf-8 -*-
'''
| @author: olivia.dou
| Created on: 2019/10/26 13:08
| desc: 和标注自动化相关的一些功能，初始想法是：标注无法随机自动化，考虑使用已提取的文件上的位置信息，对训练中模型的样本文件进行提取
'''

import requests, logging, traceback
from jsonpath import jsonpath
import base.globalvars as glo
from base.getdata import get_header
from proj_spec.DAS.model import get_model_id
from proj_spec.DAS.element import get_element_id
from util.db_util import execute_query


def convert_area(area):
    """将竖线分隔的区域信息转换为表示区域的字典

    :param area: 竖线分隔的区域信息
    :return: 表示区域的字典{"pageNum": pageNum, "x1": x1, "y1": y1, "x2": x2, "y2": y2}
    """
    if not isinstance(area, str):
        assert "无效输入：area应为|分隔的字符串"
    value_list = area.split('|')
    converted_area = {"pageNum": int(value_list[0]), "x1": float(value_list[1]), "y1": float(value_list[2]),
                      "x2": float(value_list[1]) + float(value_list[3]),
                      "y2": float(value_list[2]) + float(value_list[4])}
    return converted_area


def find_outer_range(areas):
    """根据输入的area的列表找到区域范围(upper left, bottom right)

    :param areas: 区域的列表，区域为竖线分隔的区域信息

    :return: 区域列表对应区域的左上角;右下角信息
    """

    converted_areas = [convert_area(area) for area in areas]
    min_page = sorted(converted_areas, key=lambda x: x['pageNum'])[0]['pageNum']
    min_page_areas = [area for area in converted_areas if area['pageNum'] == min_page]
    max_page = sorted(converted_areas, key=lambda x: x['pageNum'])[-1]['pageNum']
    max_page_areas = [area for area in converted_areas if area['pageNum'] == max_page]
    x1 = sorted(min_page_areas, key=lambda x: x['x1'])[0]['x1']
    y1 = sorted(min_page_areas, key=lambda x: x['y1'])[0]['y1']
    x2 = sorted(max_page_areas, key=lambda x: x['x2'], reverse=True)[0]['x2']
    y2 = sorted(max_page_areas, key=lambda x: x['y2'], reverse=True)[0]['y2']
    # logging.debug("%s,%s,%s,%s,%s,%s"%(min_page,x1,y1,max_page,x2,y2))
    # 上下边界分别减去和增加一点Delta_y值
    upper_left = [min_page, x1, y1 - 20, x1 + 100, y1 - 10]
    lower_right = [max_page, x1, y2 + 10, x1 + 100, y2 + 20]
    result_area = "%s;%s" % ('|'.join(str(v) for v in upper_left), '|'.join(str(v) for v in lower_right))
    logging.debug(result_area)
    return result_area


def get_extracted_area(model_id, element_id, file_id):
    """获取指定文件在指定模型元素下被提取的区域

    :param model_id: 模型id
    :param element_id: 元素id
    :param file_id: 文件id

    :return: 指定文件在指定模型元素下被提取的区域
    """
    from base.get_config import get_header_file
    url = glo.get_value("url1") + "/api/v1/ExtractData/filter?ModelId=%s&ElementId=%s&FileId=%s" % (
    model_id, element_id, file_id)
    headers = get_header(get_header_file(), "header1")
    res = requests.get(url, headers=headers)
    assert res.status_code == 200

    if jsonpath(res.json(), "$[*].tableArea") is not False:
        table_areas = jsonpath(res.json(), "$[*].tableArea")[0].split(';')  # json内容实际只有一个
    else:
        table_areas = []
    if jsonpath(res.json(), "$[*].textArea") is not False:
        text_areas = jsonpath(res.json(), "$[*].textArea")[0].split(';')
    else:
        text_areas = []
    logging.debug(table_areas)
    logging.debug(text_areas)

    areas = table_areas
    areas.extend(text_areas)

    outer_range = find_outer_range(areas)

    return outer_range


def get_mark_id(model_name, element_name, file_id):
    """获取指定模型、元素、文件下的主标注id
    Todo: 调用get_mark_ids
    :param model_name: 模型名称
    :param element_name: 元素名称
    :param file_id: 文件id

    :return: 模型、元素、文件下的主标注id
    """
    results = execute_query(
        "SELECT mark.id FROM `t_das_mark` as mark JOIN t_das_model as model ON mark.model_id=model.id JOIN t_das_model_element AS melement ON mark.element_id=melement.id WHERE model.model_name='%s'  AND melement.element_name='%s' AND file_id=%d" % (
        model_name, element_name, file_id))
    try:
        result = results[0][0]
        return result
    except Exception as e:
        logging.error("no result retrieved")
        return None

def get_mark_ids(**kwargs):
    """获取主标注id列表

    :param kwargs:
        | model_name：模型名称
        | model_id： 模型id
        | element_name: 元素名称
        | element_id： 元素id
        | file_id: 文件id

    :return:
    """
    query_substr = ""
    if 'model_name' in kwargs or 'model_id' in kwargs:
        if 'model_id' not in kwargs:
            model_id = get_model_id(kwargs['model_name'])
        else:
            model_id = kwargs['model_id']
        query_substr += " and model_id=%s"%model_id
    if 'element_id' in kwargs or ('element_name' in kwargs and 'model_name' in kwargs):
        # 获取元素id
        if 'element_id' not in kwargs:
            element_id = get_element_id(kwargs['model_name'],kwargs['element_name'])
        else:
            element_id = kwargs['element_name']
        query_substr += " and element_id=%s"%element_id

    if 'file_id' in kwargs:
        query_substr+=" and file_id=%s"%kwargs['file_id']

    query_substr = query_substr.lstrip(" and")

    try:
        sql = "select id from t_das_mark where %s"%query_substr
        res = execute_query(sql)
        if len(res)>0:
            return [row[0] for row in res]
        else:
            return []
    except Exception as e:
        logging.error("get_mark_ids: %s"%e)
        traceback.print_exc()
        return []



def get_marktabledetail_id(model_name, element_name, file_id, cell_name):
    """获取指定模型、元素、文件、单元格的id

    :param model_name: 模型名称
    :param element_name: 元素名称
    :param file_id: 文件id
    :param cell_name: 单元格值

    :return: 模型、元素、文件、单元格的id
    """
    results = execute_query(
        "SELECT mark.id FROM `t_das_mark_table_detail` as mark JOIN t_das_model as model ON mark.model_id=model.id JOIN t_das_model_element AS melement ON mark.element_id=melement.id WHERE model.model_name='%s'  AND melement.element_name='%s' AND file_id=%d and cell_value='%s'" % (
        model_name, element_name, file_id, cell_name))
    try:
        result = results[0][0]
        return result
    except Exception as e:
        logging.error("no result retrieved")
        return None

def get_mark_supplement_id(model_name, element_name, file_id):
    """获取指定模型、元素、文件下的补充标注id

    :param model_name: 模型名称
    :param element_name: 元素名称
    :param file_id: 文件id

    :return: 模型、元素、文件下的补充标注id
    """
    results = execute_query(
        "SELECT s.id FROM `t_das_mark_supplement` as s "
        "LEFT JOIN t_das_model as m ON s.model_id=m.id "
        "LEFT JOIN t_das_model_element AS e ON s.element_id=e.id WHERE m.model_name='%s'  AND e.element_name='%s' AND s.file_id='%s'" % (
        model_name, element_name, file_id))
    try:
        result = results[0][0]
        return result
    except Exception as e:
        logging.error("no result retrieved")
        return None

def get_mark_supplement_ids(model_name, element_name=''):
    """获取指定模型、元素下的补充标注id列表

    :param model_name: 模型名称
    :param element_name: 元素名称

    :return: 模型、元素下的补充标注id列表
    """
    if element_name !='':
        ext = """ AND e.element_name='%s'"""
    else:
        ext = ""
    sql = """SELECT s.id FROM `t_das_mark_supplement` as s 
        LEFT JOIN t_das_model as m ON s.model_id=m.id 
        LEFT JOIN t_das_model_element AS e ON s.element_id=e.id WHERE m.model_name='%s' %s""" % ( model_name, ext)
    results = execute_query(sql)
    try:
        result = results[0]
        return result
    except Exception as e:
        logging.error("no result retrieved")
        return []

# def get_entries_with_supplement_mark(model_id=None):
#     """获取有补充标注的模型或元素列表，指定model_id时，返回该模型下有补充标注的元素列表，否则返回有补充标注的模型列表
#
#     :param model_id: 模型id
#
#     :return: 模型列表或元素列表
#     """
#     if model_id is None:
#         sql = "SELECT model_id"

def get_mark_table_area(model_id, element_id, file_id):
    """获取t_das_train_extract_data或者t_das_extract_data表中的定位坐标

    :param model_id:模型名称
    :param element_id: 元素名称
    :param file_id: 文件id

    :return: 模型、元素、文件下的定位坐标
    """
    sql = "select table_area from t_das_train_extract_data where model_id = %s and element_id = %s and file_id = %s"%(model_id,element_id,file_id)
    res = execute_query(sql)
    if res == []:
        sql = "select table_area from t_das_extract_data where  model_id = %s and element_id = %s and file_id = %s"%(model_id,element_id,file_id)
        try:
            res = execute_query(sql)
        except Exception as e :
            logging.error("get_mark_table_area :%s"%e)
    return res[0][0]
